/**
 * @file phone_api.c - phone API called by other modules
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_PHONE != 0

/*********************
 *      DEFINES
 *********************/
#define PHONE_NV_VOLUME_OFFSET          0
#define PHONE_NV_EMERGENCY_NUM_OFFSET   1
#define PHONE_NV_EMERGENCY_NUM_SIZE     sizeof(nv_call_emergency_number_t)
#define PHONE_TYPE_INTERNATIONAL_ACCESS_CODE  145  //Dialing string includes international access code character "+"

/**********************
 *  STATIC VARIABLES
**********************/
extern bool callwait_flg;
extern bool call_double_flg;
phone_call_params_t  call_params;
phone_call_params_t  call_params_wait;
static bool monitor_mode = false;
static bool monitoring = false;
#if USE_LV_WATCH_CALL_LOG
hal_rtc_t time_for_call_log;
#endif

#if USE_LV_WATCH_ENGINEER_MODE!= 0
static bool auto_dialer_start = false;
static bool auto_dialer_end_call = false;
#endif

/**********************
 *   FUNCTIONS DECLARATION
***********************/
static void ceer_timeout_cb(void * para);
static void redial_timeout_cb(void * para);
static void phone_stop_all_timers(void);

lv_obj_t * phone_create(lv_obj_t * activity_obj, phone_ui_t phone_ui_id);
lv_res_t phone_ring_off_create(void);
void ring_off_action(lv_obj_t * btn, lv_event_t e);
lv_obj_t * call_prompt_create(lv_obj_t * activity_obj);
lv_obj_t * phone_call_waiting_create(char *number);

/**********************
 *   FUNCTIONS DEFINITION
***********************/
void watch_modem_call_response_originating(int32_t index)
{
    printf("%s: %d\n", __func__, index);
    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        return;
    }
    call_params.index = index;

    //state: NULL -> DIALLING
    call_params.state = MMI_MODEM_CALL_STATE_DIALING;
}

void watch_modem_call_response_alerting(int32_t index)
{
    printf("%s: state %d index %d\n", __FUNCTION__, call_params.state, index);

    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        return;
    }
    if(MMI_MODEM_CALL_STATE_ALERTING == call_params.state) {
        return;
    }

    uint8_t volume;

    //state: DIALLING -> ALERTING
    call_params.state = MMI_MODEM_CALL_STATE_ALERTING;

    //set speaker volume
    UI_NV_Read_Req(NV_SECTION_UI_PHONE, PHONE_NV_VOLUME_OFFSET, 1, &volume);
    call_params.speaker_volume = volume;
    if(!Hal_Set_BT_Audio_Path((HAL_SPEAKER_GAIN)volume))
        Hal_Call_Speaker(HAL_CALL_SPK_ON, (HAL_SPEAKER_GAIN)volume);
}

void watch_modem_call_response_ring(int32_t index)
{
    printf("%s: state %d, index %d\n", __FUNCTION__, call_params.state, index);

    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        return;
    }
    if(false == watch_is_ready()) {
        printf("%s: ignore ring during power off\n", __FUNCTION__);
        return;
    }

    if((MMI_MODEM_CALL_STATE_INCOMING == call_params.state)
        || (MMI_MODEM_CALL_STATE_DIALING == call_params.state) //ringback
        || (MMI_MODEM_CALL_STATE_ALERTING == call_params.state)) {
        return;
    }

    //stop all timers
    phone_stop_all_timers();

    //set call params
    Hal_Mem_Set(&call_params, 0, sizeof(phone_call_params_t));

    call_params.index      = index;
    call_params.is_mt      = true;
    call_params.state      = MMI_MODEM_CALL_STATE_INCOMING;
    call_params.speaker_volume = phone_get_call_speaker_volume();
}

void watch_modem_call_response_connect(int32_t index)
{
    printf("%s: state %d, index %d\n", __FUNCTION__, call_params.state, index);

    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        return;
    }
    if(MMI_MODEM_CALL_STATE_NULL == call_params.state) {
        /*"AT+CHLD=0/1X" has been sent to ril before "connect" is received*/
        watch_modem_call_request_hangup_foreground_resume_background();
        return;
    } else if(MMI_MODEM_CALL_STATE_ACTIVE == call_params.state) {
        return;
    }

#if USE_LV_WATCH_CALL_LOG
    //update call log
    bool update_call_log = false;
    if(MMI_MODEM_CALL_STATE_INCOMING == call_params.state) {
        update_call_log = true;
    }
#endif

    call_params.state = MMI_MODEM_CALL_STATE_ACTIVE;

    if(false == monitoring) {
        Hal_Tone_Play_End();

#if USE_LV_WATCH_CALL_LOG
        //update call log infomation
        if(true == update_call_log) {
            call_log_update_call_log_info(CALL_STATUS_INCOMING, call_params.number, &time_for_call_log);
        }
#endif

        //create connected UI
        phone_create(NULL, PHONE_UI_CONNECTED);

        //indicate sos
        if(false == call_params.is_mt) {
            sos_phone_dailing_status_ind(SOS_PHONE_DIAL_SUCCESS);
        }

        //set speaker volume
        uint8_t volume;
        UI_NV_Read_Req(NV_SECTION_UI_PHONE, PHONE_NV_VOLUME_OFFSET, 1, &volume);
        call_params.speaker_volume = volume;
        if(!Hal_Set_BT_Audio_Path((HAL_SPEAKER_GAIN)volume))
            Hal_Call_Speaker(HAL_CALL_SPK_ON, (HAL_SPEAKER_GAIN)volume);
    }
}

void watch_modem_call_response_disconnect(int32_t index)
{
    printf("%s: %d,callwait_flg is %d,call_double_flg is %d\n", __func__, index,callwait_flg,call_double_flg);
    lv_phone_obj_ext_t *ext = phone_get_ext();
    if(callwait_flg) {
        callwait_flg = false;
        if(index == call_params_wait.index) {
            Hal_Mem_Set(&call_params_wait, 0, sizeof(phone_call_params_t));
            if(ext->phone_animation_obj) {
                lv_obj_del(ext->phone_animation_obj);
                ext->phone_animation_obj = NULL;
            }
            if(ext->callwait_img) {
                lv_obj_del_async(ext->callwait_img);
                ext->callwait_img = NULL;
            }
#if USE_LV_WATCH_CALL_LOG
            call_log_update_call_log_info(CALL_STATUS_MISSED, call_params_wait.number, &time_for_call_log);
#endif
        } else {
            if(ext->phone_animation_obj) {
                lv_obj_del(ext->phone_animation_obj);
                ext->phone_animation_obj = NULL;
            }
            MMI_Modem_Call_Response_Clip_t * clip = (MMI_Modem_Call_Response_Clip_t *)lv_mem_alloc(sizeof(MMI_Modem_Call_Response_Clip_t));
            memset(clip,0,sizeof(MMI_Modem_Call_Response_Clip_t));
            clip->number = lv_strdup(call_params_wait.number);
            clip->type = 0;
            int32_t index_new = call_params_wait.index;
            Hal_Mem_Set(&call_params, 0, sizeof(phone_call_params_t));
            Hal_Mem_Set(&call_params_wait, 0, sizeof(phone_call_params_t));
            watch_modem_call_response_clip_auto(index_new, clip);
        }
    }
    if(call_double_flg) {
        call_double_flg = false;
        if(index != call_params_wait.index) {
            Hal_Mem_Copy(&call_params,&call_params_wait,sizeof(phone_call_params_t));
            ext->connect_start_time = ext->connect_start_time2;
            watch_modem_call_request_hangup_foreground_resume_background();
        }
        Hal_Mem_Set(&call_params_wait, 0, sizeof(phone_call_params_t));
        if(ext->callwait_img) {
            lv_obj_del_async(ext->callwait_img);
            ext->callwait_img = NULL;
        }
        lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(lv_obj_get_parent(ext->num_label));
        char txt[NV_CONTACTS_MAX_NAME_LEN + NV_CONTACTS_MAX_NUMBER_LEN] = {};
        if(LV_BIDI_DIR_RTL == bidi_dir) {
            lv_obj_set_base_dir(ext->num_label, LV_BIDI_DIR_LTR);
            strcat(txt, call_params.number);
            if(strlen(call_params.name) > 0) {
                strcat(txt, " ");
                strcat(txt, call_params.name);
            }
        } else {
            if(strlen(call_params.name) > 0) {
                strcat(txt, call_params.name);
                strcat(txt, " ");
            }
            strcat(txt, call_params.number);
        }
        lv_label_set_text(ext->num_label, txt);
    }
}

void watch_modem_call_response_dial(uint8_t isOk)
{
    printf("%s: %d\n", __func__, isOk);
    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        return;
    }
    if(false == call_params.waiting_response_dial) {
        printf("%s: ignore response dial\n", __func__);
        return;
    }

    if(0 == isOk) { // OK
#if USE_LV_WATCH_CALL_LOG
        //update call log information
        call_log_update_call_log_info(CALL_STATUS_OUTGOING, call_params.number, &time_for_call_log);
#endif

        call_params.waiting_response_dial = false;
        //stop all timers
        phone_stop_all_timers();

        if(MMI_MODEM_CALL_STATE_NULL == call_params.state) {
            call_params.state = MMI_MODEM_CALL_STATE_DIALING;
        }
    } else { // CME ERROR
        if(MMI_MODEM_CALL_SERVICE_EMERGENCY == call_params.service_type) {
            if(call_params.redial_cnt >= REDIAL_MAX_CNT) {
                watch_modem_call_response_no_carrier(-1, 0);
            } else {
                //start redial timer
                if(NULL == call_params.redial_timer_id) {
                    printf("%s: start redial timer\n", __func__);
                    call_params.redial_timer_id = Hal_Timer_Start(REDIAL_TIMER_LEN, redial_timeout_cb, NULL, 0);
               }
            }
        } else {
            //wait for response ceer
            if(NULL == call_params.ceer_timer_id) {
                printf("%s: start ceer timer\n", __func__);
                call_params.ceer_timer_id = Hal_Timer_Start(CEER_TIMER_LEN, ceer_timeout_cb, NULL, 0);
           }
        }
    }
}

void watch_modem_call_response_no_carrier(int32_t index, uint8_t isNoCarrier)
{
    bool switch_path = false;
    if(call_params.state != MMI_MODEM_CALL_STATE_NULL) {
        watch_wakeup_lcd(false);
    }
    if((false == call_params.ring_off_timeout)
            && (1 == isNoCarrier)
            && (MMI_MODEM_CALL_STATE_NULL == call_params.state)) {
        printf("%s: ignore no carrier in state NULL\n", __func__);
        return;
    }

    printf("%s: %d,%d\n", __func__, index, isNoCarrier);
    if(false == monitoring) {
        //stop playing tone
        Hal_Tone_Play_End();

        //create ring off UI
        lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_PHONE);
        if(activity_obj) {
            phone_ring_off_create();
        }

#if USE_LV_WATCH_CALL_LOG
        //update call log information
        if(MMI_MODEM_CALL_STATE_INCOMING == call_params.state) {
            printf("%s: ring_off_timeout = %d, ring_off = %d\n", __FUNCTION__, call_params.ring_off_timeout, call_params.ring_off);
            if(true == call_params.ring_off) {
                call_log_update_call_log_info(CALL_STATUS_REJECTED, call_params.number, &time_for_call_log);
            } else {
                call_log_update_call_log_info(CALL_STATUS_MISSED, call_params.number, &time_for_call_log);
            }
        }
        call_log_ui_update();
#endif

        //set voice call status
        Hal_Set_Voice_Call_Status(VOICE_CALL_END);
        //disconnect BT audio path
        switch_path = Hal_Disconnect_BT_Audio_Path();

        //indicate sos
        if((false == call_params.is_mt) && (MMI_MODEM_CALL_STATE_ACTIVE != call_params.state)) {
            if(call_params.ring_off) {
                sos_phone_dailing_status_ind(SOS_PHONE_DIAL_SUCCESS);
            } else {
                sos_phone_dailing_status_ind(SOS_PHONE_DIAL_FAIL);
            }
        }

#if USE_LV_WATCH_ENGINEER_MODE!= 0
        //indicate auto dialer
        if(auto_dialer_start) {
            if(call_params.ring_off && !auto_dialer_end_call) { //ring off by user
                engineer_mode_auto_dialer_test_result_ind(EVENT_FINISH);
            } else {
                auto_dialer_end_call = false;
                engineer_mode_auto_dialer_test_result_ind(EVENT_END_CALL);
            }
        }
#endif
    } else {
        monitoring = false;
    }

    //stop all timers
    phone_stop_all_timers();

#if 0
    //display alarm if it is buffered
    if(call_params.buffer_alarm) {
        call_params.buffer_alarm = false;
        Hal_NFFS_File_Play_Repeat(AUDIO_ALARM, query_current_volume());
        alarm_create(NULL);
    } else {
        //indicate voice msg
        voice_msg_call_end();
    }
#endif
    if(switch_path) {
#if USE_LV_BLUETOOTH
        watch_bt_sco_set_call_type(0);
#endif
    } else{
        Hal_Audio_Manage_End_Ind(AUDIO_CTRL_PRIORITY_1);
    }
    Hal_Mem_Set(&call_params, 0, sizeof(phone_call_params_t));
    call_params.state = MMI_MODEM_CALL_STATE_NULL;
}

void watch_modem_call_response_clip(int32_t index, MMI_Modem_Call_Response_Clip_t * clip)
{
    phonebook_contact_t * contact_info = NULL;
    char * number = NULL;

    if(false == watch_is_ready()||(true == callwait_flg)) {
        printf("%s: ignore clip during power off or callwait flg is %d\n", __FUNCTION__,callwait_flg);
        Hal_Mem_Free(clip->number);
        Hal_Mem_Free(clip);
        return;
    }

    if((MMI_MODEM_CALL_STATE_INCOMING == call_params.state)
            && (strlen(call_params.number) > 0)) {
        Hal_Mem_Free(clip->number);
        Hal_Mem_Free(clip);
        return;
    }

    printf("%s: index=%d, number=%s, type=%d\n", __func__, index, clip->number, clip->type);

    //stop all timers
    phone_stop_all_timers();

    //set call params
    Hal_Mem_Set(&call_params, 0, sizeof(phone_call_params_t));
    call_params.index      = index;
    call_params.is_mt      = true;
    call_params.state      = MMI_MODEM_CALL_STATE_INCOMING;
    call_params.speaker_volume = phone_get_call_speaker_volume();
    if((PHONE_TYPE_INTERNATIONAL_ACCESS_CODE == clip->type) && ('+' != clip->number[0])) {
        call_params.number[0] = '+';
        strncpy(call_params.number + 1, clip->number, NV_CONTACTS_MAX_NUMBER_LEN - 1);
        printf("%s: number=%s\n", __func__, call_params.number);
    } else {
        strncpy(call_params.number, clip->number, NV_CONTACTS_MAX_NUMBER_LEN);
    }

    number = phonebook_get_phone_number(0);
    if(NULL == number) {    //no contact
        contact_info = (phonebook_contact_t *)Hal_Mem_Alloc(sizeof(phonebook_contact_t));
        Hal_Mem_Set(contact_info, 0, sizeof(phonebook_contact_t));
        contact_info->img_src = ICON_FAMILY;
        contact_info->img_src_small = ICON_FAMILY_SMALL;
        contact_info->contact_type = 2;
        Hal_Mem_Free(clip->number);
    } else {
        Hal_Mem_Free(number);
        contact_info = phonebook_get_contact_info(clip->number);
    }

    if(NULL != contact_info) {
        Hal_Mem_Copy(call_params.name, contact_info->contact_name, NV_CONTACTS_MAX_NAME_LEN);
        call_params.img_src = contact_info->img_src;
        call_params.img_src_small = contact_info->img_src_small;

        if((true == monitor_mode)
                && ((0 == contact_info->contact_type) || (1 == contact_info->contact_type))) {
            monitoring = true;
        }

        Hal_Mem_Free(contact_info);
#if 0
        //inform speech recog & voice msg
        speech_recog_mt_call_ind();
        voice_msg_mt_call_ind();

        if(voip_connect_check_req())
            voip_activity_destroy_req();
#endif
        Hal_Audio_Manage_Start_Req(AUDIO_CTRL_PRIORITY_1,phone_audio_ctrl_callback);
        if(false == monitoring) {
#if 0
            //clean up alarm if any
            alarm_cleanup();
#endif
#if USE_LV_WATCH_ENGINEER_MODE!= 0
            nv_watch_engineer_mode_t               engineermode;
            UI_NV_Read_Req(NV_SECTION_UI_ENGINEER_MODE, 0, sizeof(nv_watch_engineer_mode_t), (uint8_t *)&engineermode);
            if(AUTO_ANSWER_ENABLE == engineermode.autoanswerflg) {
                //auto answer
                watch_modem_call_request_answer();
            } else
#endif
            {
                //set speaker volume
                uint8_t volume;
                UI_NV_Read_Req(NV_SECTION_UI_PHONE, PHONE_NV_VOLUME_OFFSET, 1, &volume);
                Hal_Call_Speaker(HAL_CALL_SPK_ON, (HAL_SPEAKER_GAIN)volume);
                call_params.speaker_volume = volume;

                //play tone
                Hal_NFFS_File_Play_Repeat(AUDIO_INCOMING_CALL, query_current_volume());

#if USE_LV_WATCH_CALL_LOG
                //record time for call log
                memset(&time_for_call_log, 0, sizeof(hal_rtc_t));
                Hal_Rtc_Gettime(&time_for_call_log);
#endif

                //create ring UI
                phone_create(NULL, PHONE_UI_RING);

                //wakeup lcd
                watch_set_lcd_status(true);
            }
        } else {
            printf("%s: monitoring, auto answer\n", __func__);
            //auto answer
            watch_modem_call_request_answer();
            Hal_Call_Speaker(HAL_CALL_SPK_ON, HAL_AUDIO_SPK_MUTE);

#if PHONE_TEST
            watch_modem_call_response_connect(call_params.index);
#endif
        }
    } else {
        printf("%s: not a contact, auto reject\n", __func__);
        //auto reject
        call_params.state = MMI_MODEM_CALL_STATE_NULL;
        watch_modem_call_request_udub();

#if PHONE_TEST
        watch_modem_call_response_no_carrier(call_params.index, 0);
#endif
    }

    Hal_Mem_Free(clip);
}

void watch_modem_call_response_ccwa(int32_t index, MMI_Modem_Call_Response_Ccwa_t *ccwa)
{
    printf("%s:index is %d,ccwa->number is %s\n",__FUNCTION__,index,ccwa->number);
    char * num_info = lv_strdup(ccwa->number);
    phonebook_contact_t * contact_info = phonebook_get_contact_info(num_info);
    if(NULL == contact_info) {
        printf("%s: contact_info is NULL!\n", __FUNCTION__);
        watch_modem_call_request_udub();
        Hal_Mem_Free(ccwa->number);
        Hal_Mem_Free(ccwa);
        return;
    }
    if(true == monitoring) {
        printf("%s: monitoring is %d\n", __FUNCTION__, monitoring);
        watch_modem_call_request_udub();
        Hal_Mem_Free(ccwa->number);
        Hal_Mem_Free(ccwa);
        return;
    }
    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        Hal_Mem_Free(ccwa->number);
        Hal_Mem_Free(ccwa);
        return;
    }
#if USE_LV_WATCH_CALL_LOG
    //record time for call log
    memset(&time_for_call_log, 0, sizeof(hal_rtc_t));
    Hal_Rtc_Gettime(&time_for_call_log);
#endif
    callwait_flg = true;
    if(NULL == phone_call_waiting_create(ccwa->number)) {
        callwait_flg = false;
        call_double_flg = false;
    } else {
        //wakeup lcd
        watch_set_lcd_status(true);
    }

    Hal_Mem_Free(ccwa->number);
    Hal_Mem_Free(ccwa);
}

void watch_modem_call_response_state_change(MMI_Modem_Call_Response_State_Change_t * state)
{
    for(uint8_t i = 0; i < state->count; i++) {
        Hal_Mem_Free(state->calls[i].number);
        Hal_Mem_Free(state->calls[i].name);
    }
    Hal_Mem_Free(state->calls);
    Hal_Mem_Free(state);
}

void watch_modem_call_response_ceer(char *ceer)
{
    printf("%s: %s\n", __func__, ceer);
    if((true == callwait_flg) || (true == call_double_flg)) {
        printf("%s: callwait_flg %d,call_double_flg is %d\n", __FUNCTION__, callwait_flg,call_double_flg);
        return;
    }

    if(NULL == call_params.ceer_timer_id) {
        printf("%s: ceer timer is stopped or expired\n", __func__);
        Hal_Mem_Free(ceer);
        return;
    }

    //stop ceer timer
    Hal_Timer_Stop(call_params.ceer_timer_id);
    call_params.ceer_timer_id = NULL;

    const char *str = "251"; //"251 IN REGISTER"
    if(NULL != strstr(ceer, str)) {
        if(call_params.redial_cnt >= REDIAL_MAX_CNT) {
            watch_modem_call_response_no_carrier(-1, 0);
        } else {
            //start redial timer
            if(NULL == call_params.redial_timer_id) {
                printf("%s: start redial timer\n", __func__);
                call_params.redial_timer_id = Hal_Timer_Start(REDIAL_TIMER_LEN, redial_timeout_cb, NULL, 0);
           }
        }
    } else {
        watch_modem_call_response_no_carrier(-1, 0);
    }

    Hal_Mem_Free(ceer);
}

void phone_voice_call_req(char * number)
{
    nv_call_emergency_number_t enumber;
    MMI_MODEM_CALL_SERVICE_TYPE service_type = MMI_MODEM_CALL_SERVICE_NORMAL;
    uint8_t sim_present = 0;
    char * dial_number = NULL;

    //check call state
    if(MMI_MODEM_CALL_STATE_NULL != call_params.state) {
        printf("%s: only support one call, state=%d, monitoring=%d\n", __func__, call_params.state, monitoring);
        Hal_Mem_Free(number);
        return;
    }
    printf("%s: %s\n",  __func__, number);

    //check sim status
#if PHONE_TEST
    sim_present = 1;
#else
    sim_present = watch_modem_sim_present_check_req();
#endif

    if(0 == sim_present) {
        //check if it's an emergency call
        UI_NV_Read_Req(NV_SECTION_UI_PHONE, PHONE_NV_EMERGENCY_NUM_OFFSET, PHONE_NV_EMERGENCY_NUM_SIZE, (uint8_t *)&enumber);

        for(uint8_t i = 0; i < enumber.number_cnt; i++) {
            if(!strcmp(enumber.number[i], number)) {
                printf("%s: emergency call %s without sim\n",  __func__, number);
                service_type = MMI_MODEM_CALL_SERVICE_EMERGENCY;
                break;
            }
        }

        if(MMI_MODEM_CALL_SERVICE_NORMAL == service_type) {
            printf("%s: can not initiate a normal call without sim\n",  __func__);
            call_prompt_create(NULL);
            Hal_Mem_Free(number);
            return;
        }
    }

    //stop all timers
    phone_stop_all_timers();

    Hal_Audio_Manage_Start_Req(AUDIO_CTRL_PRIORITY_1,phone_audio_ctrl_callback);
    //set speaker volume, no connect at response for 112, so set volume and call status here
    uint8_t volume;
    UI_NV_Read_Req(NV_SECTION_UI_PHONE, PHONE_NV_VOLUME_OFFSET, 1, &volume);
    if(!Hal_Set_BT_Audio_Path((HAL_SPEAKER_GAIN)volume))
        Hal_Call_Speaker(HAL_CALL_SPK_ON, (HAL_SPEAKER_GAIN)volume);
    Hal_Set_Voice_Call_Status(VOICE_CALL_START);

    //set call params
    Hal_Mem_Set(&call_params, 0, sizeof(phone_call_params_t));
    call_params.is_mt = false;
    call_params.state = MMI_MODEM_CALL_STATE_NULL;
    call_params.speaker_volume = volume;
    call_params.service_type = service_type;

    strncpy(call_params.number, number, NV_CONTACTS_MAX_NUMBER_LEN);

    phonebook_contact_t * contact_info = phonebook_get_contact_info(number);
    if(NULL != contact_info) {
        Hal_Mem_Copy(call_params.name, contact_info->contact_name, NV_CONTACTS_MAX_NAME_LEN);
        call_params.img_src = contact_info->img_src;
        call_params.img_src_small = contact_info->img_src_small;

        Hal_Mem_Free(contact_info);
    } else {
        call_params.img_src = ICON_FAMILY;
        call_params.img_src_small = ICON_FAMILY_SMALL;
    }

    //Initiate voice call
    dial_number = (char *)Hal_Mem_Alloc(strlen(call_params.number) + 1);
    strncpy(dial_number, call_params.number, strlen(call_params.number) + 1);
    watch_modem_call_request_dial(dial_number, service_type);

    call_params.waiting_response_dial = true;

#if USE_LV_WATCH_CALL_LOG
    //record call log time of outgoing call
    memset(&time_for_call_log, 0, sizeof(hal_rtc_t));
    Hal_Rtc_Gettime(&time_for_call_log);
#endif

    //create dialing UI
    phone_create(NULL, PHONE_UI_DIALING);
}

void app_adaptor_set_monitor(bool monitor)
{
    monitor_mode = monitor;
}

void phone_init(void)
{
    Hal_Mem_Set(&call_params, 0, sizeof(phone_call_params_t));
    call_params.state = MMI_MODEM_CALL_STATE_NULL;
}

uint8_t phone_get_call_speaker_volume(void)
{
    uint8_t volume = (uint8_t)HAL_AUDIO_SPK_LEVEL_MAX;

    UI_NV_Read_Req(NV_SECTION_UI_PHONE, PHONE_NV_VOLUME_OFFSET, 1, &volume);
    return volume;
}

#if USE_LV_WATCH_ENGINEER_MODE!= 0
void engineer_mode_auto_dialer_test_req(bool start)
{
    auto_dialer_start = start;

    if(!start) {
        auto_dialer_end_call = false;
    }
}

void engineer_mode_auto_dialer_end_call_req(void)
{
    auto_dialer_end_call = true;

    //ring off
    ring_off_action(NULL, LV_EVENT_CLICKED);
}

#endif

bool phone_is_monitor_on(void)
{
    return monitor_mode;
}

#if 0
void phone_alarm_ind(void)
{
    call_params.buffer_alarm = true;
}
#endif

MMI_MODEM_CALL_STATE phone_get_call_state(void)
{
    return(call_params.state);
}

bool watch_phone_suspend_check(void)
{
    if((MMI_MODEM_CALL_STATE_DIALING  != phone_get_call_state()) &&
            (MMI_MODEM_CALL_STATE_ALERTING != phone_get_call_state()) &&
            (MMI_MODEM_CALL_STATE_INCOMING != phone_get_call_state()))
        return true;
    return false;
}

static void ceer_timeout_cb(void * para)
{
    call_params.ceer_timer_id = NULL;
    printf("%s: number=%s\n", __func__, call_params.number);

    watch_modem_call_response_no_carrier(-1, 0);
}

static void redial_timeout_cb(void * para)
{
    call_params.redial_timer_id = NULL;
    call_params.redial_cnt ++;
    printf("%s: number=%s, redial_cnt=%d\n", __func__, call_params.number, call_params.redial_cnt);

    //redial
    char * number = Hal_Mem_Alloc(strlen(call_params.number) + 1);
    strncpy(number, call_params.number, strlen(call_params.number) + 1);
    watch_modem_call_request_dial(number, call_params.service_type);
}

static void phone_stop_all_timers(void)
{
    //stop ring off timer
    if(NULL != call_params.ring_off_timer_id) {
        Hal_Timer_Stop(call_params.ring_off_timer_id);
        call_params.ring_off_timer_id = NULL;
    }

    //stop ceer timer
    if(NULL != call_params.ceer_timer_id) {
        Hal_Timer_Stop(call_params.ceer_timer_id);
        call_params.ceer_timer_id = NULL;
    }

    //stop redial timer
    if(NULL != call_params.redial_timer_id) {
        Hal_Timer_Stop(call_params.redial_timer_id);
        call_params.redial_timer_id = NULL;
    }
    call_params.redial_cnt = 0;
}

#if USE_LV_BLUETOOTH
static int8_t last_volume = -1;
static int8_t  call_type = -1;   //0--phone call, 1--voip call
void watch_bt_sco_set_call_type(int8_t type)
{
    call_type = type;
}

void watch_bt_hfp_ata_message_handle(void)
{
    ring_hook_action(NULL, LV_EVENT_CLICKED);
}

void watch_bt_hfp_atchup_message_handle(void)
{
    ring_off_action(NULL, LV_EVENT_CLICKED);
}

void watch_bt_hfp_dial_message_handle(void)
{
    char * number = NULL;

    //no call history in watch, so call index 0(manager) in contact
    number = phonebook_get_phone_number(0);
    if(NULL == number) {    //no contact
        printf("%s: no contact, dail fail\n", __FUNCTION__);
    } else {
        printf("%s: call manager\n", __FUNCTION__);
        phone_voice_call_req(number);
    }
}

void watch_bt_hfp_atchld_message_handle(void)
{
    printf("void function %s", __FUNCTION__);
}

void watch_bt_hfp_recognition_message_handle(void * msg)
{
    printf("void function %s", __FUNCTION__);
}

static void bt_slider_action(lv_obj_t * slider, lv_event_t event)
{
    if(LV_EVENT_VALUE_CHANGED != event) return;
    if(!lv_slider_is_dragged(slider)) return;

    uint8_t v = lv_slider_get_value(slider);

    printf("%s\n", __FUNCTION__);
    //set bt volume
    appbt_hfp_set_speaker_gain(v);
}

void watch_bt_hfp_speaker_volume_message_handle(void * msg)
{
    lv_obj_t * bt_volume_slider;
    int32_t current_volume = ((mmi_msg_bt_hfp_value_response_t *)msg)->value;

    printf("%s volume is %d\n", __FUNCTION__, current_volume);

    if((last_volume == -1) || (last_volume == current_volume)) {
        last_volume = current_volume;
        if(!lv_watch_get_activity_obj(ACT_ID_SLIDER))
            return;
    }

    last_volume = current_volume;

    lv_obj_t * act_phone = lv_watch_get_activity_obj(ACT_ID_PHONE);
    lv_obj_t * act_voip = lv_watch_get_activity_obj(ACT_ID_VOIPPHONE);

    // do not display slider outside phone voip and player APP.
    if((act_phone == NULL) && (act_voip == NULL)) return;

    bt_volume_slider = slider_create(NULL, SETTING_BT_VOLUME, 40, bt_slider_action);
    lv_slider_set_value(bt_volume_slider, current_volume, LV_ANIM_OFF);
}

void watch_bt_hfp_microphone_gain_message_handle(void * msg)
{
    printf("void function %s", __FUNCTION__);
}

void watch_bt_hfp_connected_message_handle(void)
{
    if((MMI_MODEM_CALL_STATE_ALERTING == phone_get_call_state()) ||
       (MMI_MODEM_CALL_STATE_ACTIVE == phone_get_call_state())) {
        last_volume = -1;
        Hal_Set_BT_Audio_Path((HAL_SPEAKER_GAIN)phone_get_call_volume());
    }
}
void watch_bt_hfp_disconnect_message_handle(void)
{
    if((MMI_MODEM_CALL_STATE_ALERTING == phone_get_call_state()) ||
        (MMI_MODEM_CALL_STATE_ACTIVE == phone_get_call_state())) {
        Hal_Call_Speaker(HAL_CALL_SPK_ON, (HAL_SPEAKER_GAIN)phone_get_call_volume());
    }
}

void watch_bt_sco_disconnetct_message_handle(void)
{
    printf("%s call_type = %d\n", __FUNCTION__, call_type);
    if(call_type == 0)
        Hal_Audio_Manage_End_Ind(AUDIO_CTRL_PRIORITY_1);
    else if(call_type == 1)
        Hal_Audio_Manage_End_Ind(AUDIO_CTRL_PRIORITY_2);
    call_type = -1;
}
#endif
#endif /*USE_LV_WATCH_PHONE*/
